package com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.service.impl;

import com.css.fxfzfxqh.base.dict.repository.entity.DictItemEntity;
import com.css.fxfzfxqh.base.dict.service.DictItemService;
import com.css.fxfzfxqh.base.dict.service.DictService;
import com.css.fxfzfxqh.constants.YNEnum;
import com.css.fxfzfxqh.modules.buildingIndividual.entity.BuildingIndividualEntity;
import com.css.fxfzfxqh.modules.buildings.calculationTasks.entity.CalculationTasks;
import com.css.fxfzfxqh.modules.buildings.calculationTasks.entity.YSXMainTable;
import com.css.fxfzfxqh.modules.buildings.calculationTasks.repository.CalculationTasksRepository;
import com.css.fxfzfxqh.modules.buildings.definitiveEvaluation.casualtiesDE.entity.PCC;
import com.css.fxfzfxqh.modules.buildings.definitiveEvaluation.casualtiesDE.vo.Grid13VO;
import com.css.fxfzfxqh.modules.buildings.definitiveEvaluation.util.YSXUtil;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.publicOperate.entity.PsHazardDataValue;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.publicOperate.service.PublicOperateService;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.publicOperate.vo.BasicLibraryVo;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.entity.ResistEarthquakesPECalculation;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.param.PETasksParam;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.repository.ResistEarthquakesPERepository;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.service.ResistEarthquakesPEService1;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.service.ResistEarthquakesPEService2;
import com.css.fxfzfxqh.modules.util.Calculation;
import com.css.fxfzfxqh.modules.util.hypergraph.service.HypergraphService;
import com.css.fxfzfxqh.modules.util.repository.PccRepository;
import com.css.fxfzfxqh.util.PlatformDateUtils;
import com.css.fxfzfxqh.util.PlatformObjectUtils;
import com.css.fxfzfxqh.util.UUIDGenerator;
import com.css.fxfzfxqh.web.PlatformSessionContext;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author Dbj
 * @date 2024年02月04日  9:24
 */
@Service
public class ResistEarthquakesPEService2Impl implements ResistEarthquakesPEService2 {

    @Resource
    private ResistEarthquakesPERepository resistEarthquakesPERepository;
    @Resource
    private CalculationTasksRepository calculationTasksRepository;
    @Resource
    PccRepository pccRepository;
    @Resource
    DictService dictService;
    @Resource
    DictItemService dictItemService;
    @Resource
    private PublicOperateService publicOperateService;
    @Resource
    YSXUtil ysxUtil;

    @Resource
    ResistEarthquakesPEService1 resistEarthquakesPEService1;
    @Resource
    HypergraphService hypergraphService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void calculation(PETasksParam param) throws Exception {
        long l = System.currentTimeMillis();
        System.out.println("概率评估-结构破坏计算开始：{}");
        //删除之前生成的评估数据
        resistEarthquakesPERepository.deleteCalculation(param.getTaskId());
        //获取任务
        CalculationTasks tasks = calculationTasksRepository.findById(param.getTaskId());
        //获取选择或勾选的区域信息
        List<PCC> list = pccRepository.queryToponym(tasks.getId());
        tasks.setList(list);
        //获取评估数据类别 0为烈度,1为pga  超越概率转化成发生概率
        String ldPga = tasks.getLdPga();
        if("0".equals(ldPga)){
            //发生概率地震危险性烈度
            fSLDCalculation(tasks);
        }else{
            for (int j = 2; j <= 5; j++) {
                //PGA
                try {
                    resistEarthquakesPEService1.FSPGACalculation("pgcd"+j,tasks);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //修改计算进度
        if (tasks.getSeismicInputMode().equals("3")) {
            calculationTasksRepository.updateFSProgress(tasks.getId(), "评估", "结构破坏");
        } else {
            calculationTasksRepository.updateCYProgress(tasks.getId(), "评估", "结构破坏");
        }
        boolean bool = hypergraphService.getWorkspaceReload("fxqh_resist_earthquakes_calculation_pd");
        System.out.println("概率评估-结构破坏计算结束，共用时：{}"+(System.currentTimeMillis()-l)/1000+"s");
    }

    /**
     * 发生概率地震危险性烈度计算
     */
    private void fSLDCalculation(CalculationTasks tasks) throws Exception {
        //根据任务获取合并的空间范围
        String unionGeomByCode = getUnionGeomByCode(tasks);
        //发生概率
        Map<String, List<PsHazardDataValue>> mapVXX = null;
        //超越概率
        Table<String, List<String>, List<BigDecimal>> stringMapMap = HashBasedTable.create();
        //地震输入方式0为设定烈度1为四个概率,2为地震影响场,  3为发生概率危险性,4为超越概率危险性,多个数字之间用,分隔
        String seismicInputMode = tasks.getSeismicInputMode();
        if("3".equals(seismicInputMode)){
            //该省市县下面的所有危险性   根据数据级别（国家级或自定义(省市区县)）和年份来查询发生概率危险性数据
            mapVXX = getIdGroupData(unionGeomByCode,tasks);
        }else{
            String type = "1";
            if ("1".equals(tasks.getHouseDataFlag())) {
                type = "0";
            }
            //重新组装
            stringMapMap = publicOperateService.transition1(unionGeomByCode, tasks.getBeyondProbabilisticVersion(), type);
        }
        if(mapVXX == null){
            throw new RuntimeException("计算未完成,没有获取到任务区域范围内的危险性数据");
        }
        //将危险性根据格网id合并
        //十三个结构类型的值的list;计算用
        List<Calculation> calculationList = new ArrayList<>();
        String houseDataFlag = tasks.getHouseDataFlag();
        if ("1".equals(houseDataFlag)) {
            //1为网格数据
            //获取烈度的公里网格
            List<Grid13VO> gridDataList = calculationTasksRepository.getGlGwDate(tasks.getId(), null);
            if(PlatformObjectUtils.isEmpty(gridDataList)){
                throw new RuntimeException("计算失败，没有获取到网格数据");
            }
            Map<String, List<Grid13VO>> collect = gridDataList.stream().filter(grid13VO -> StringUtils.isNotBlank(grid13VO.getExtends1())).collect(Collectors.groupingBy(Grid13VO::getExtends1));
            Map<String, Map<String, List<YSXMainTable>>> listMapMap = new HashMap<>();
            Map<String, List<PsHazardDataValue>> finalMapVXX = mapVXX;
            Table<String, List<String>, List<BigDecimal>> finalStringMapMap = stringMapMap;
            List<ResistEarthquakesPECalculation> finaConditionValue = new ArrayList<>();
            collect.forEach((k111, v111)->{
                //获取13类结果属于同一格网的总面积
                double gridTotalArea = v111.stream().mapToDouble(Grid13VO::getTotalArea).sum();
                //获取危险性数据
                List<PsHazardDataValue> psHazardDataValues = new ArrayList<>();
                if ("3".equals(seismicInputMode)) {
                    psHazardDataValues = finalMapVXX.get(k111);
                }else {
                    //超越概率转换
                    Map<List<String>, List<BigDecimal>> row = finalStringMapMap.row(k111);
                    if (null != row) {
                        for (Map.Entry<List<String>, List<BigDecimal>> row1 : row.entrySet()) {
                            for (int i = 0; i < row1.getKey().size(); i++) {
                                PsHazardDataValue psHazardDataValue = new PsHazardDataValue();
                                psHazardDataValue.setImValue(row1.getKey().get(i));
                                psHazardDataValue.setFImValue(row1.getValue().get(i));
                                psHazardDataValues.add(psHazardDataValue);
                            }
                        }
                    }
                }
                //以行政区域为单位组建易损性数据 相同格网的不同建筑物结构的省市县是相同的只需汇总一次即可
                //listMapMap <省_市_区县,<结构类型-设防烈度,<破坏程度，实体对象>>>
                buildYsxMap(listMapMap,v111.get(0),tasks.getId());
                if (PlatformObjectUtils.isNotEmpty(psHazardDataValues) && psHazardDataValues.size()>0) {
                    Map<String,BigDecimal> resultMap = new HashMap<>();
                    for (Grid13VO obj : v111) {
                        //获取某一类建筑类型在不同破坏程度下的概率值
                        calculationByFortification(obj,listMapMap,psHazardDataValues,"1",gridTotalArea,resultMap);
                    }
                    //汇总相同格网的不同建筑结构的数据
                    List<ResistEarthquakesPECalculation> conditionValue = getConditionValue(resultMap, tasks,gridTotalArea,v111.get(0));
                    finaConditionValue.addAll(conditionValue);
                }
            });
            //入库
            if (finaConditionValue.size() > 0) {
                resistEarthquakesPERepository.batchCalculation(finaConditionValue);
            }
        } else {
            //获取建筑物一级结构类型名称
            List<DictItemEntity> dictItemNameByDictId = dictItemService.getDictItemList("");
            Map<String, String> dictItemLevel1 = dictItemNameByDictId.stream().filter(dictItemEntity -> "100002".equals(dictItemEntity.getDictId())).collect(Collectors.toMap(DictItemEntity::getDictItemCode, DictItemEntity::getDictItemName));
            Map<String, String> dictItemLevel2 = dictItemNameByDictId.stream().collect(Collectors.toMap(DictItemEntity::getDictItemCode, DictItemEntity::getDictItemName));
            //单体数据
            List<BuildingIndividualEntity> all = calculationTasksRepository.getMonomerDate(tasks.getId());
            List<ResistEarthquakesPECalculation> finaConditionValue = new ArrayList<>();
            for (BuildingIndividualEntity obj : all) {
                //根据房屋单体经纬度获取对应发生概率
                List<PsHazardDataValue> psValue = new ArrayList<>();
                if("3".equals(seismicInputMode)){
                    //根据房屋单体经纬度获取对应发生概率
                    psValue = publicOperateService.getFSGLbyLonAndLat1(obj.getLongitude(), obj.getLatitude(), "1",tasks);
                }else {
                    //todo 需要修改
                    //根据房屋单体经纬度获取对应超越概率
                    for (String rowKey : stringMapMap.rowKeySet()) {
                        Boolean boo = resistEarthquakesPERepository.getSTIntersects(rowKey, obj.getLongitude(), obj.getLatitude());
                        if (boo) {
                            Map<List<String>, List<BigDecimal>> row = stringMapMap.row(rowKey);
                            if (null != row) {
                                for (Map.Entry<List<String>, List<BigDecimal>> row1 : row.entrySet()) {
                                    for (int i = 0; i < row1.getKey().size(); i++) {
                                        PsHazardDataValue psHazardDataValue = new PsHazardDataValue();
                                        psHazardDataValue.setImValue(row1.getKey().get(i));
                                        psHazardDataValue.setFImValue(row1.getValue().get(i));
                                        psValue.add(psHazardDataValue);
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                if (PlatformObjectUtils.isEmpty(psValue) || psValue.size()==0) {
                    continue;
                }
                //将房屋单体转换成13VO
                Grid13VO grid13VO = get13VO(obj,dictItemLevel1,dictItemLevel2);
                Map<String, Map<String, List<YSXMainTable>>> listMapMap = new HashMap<>();
                //以行政区域为单位组建易损性数据
                buildYsxMap(listMapMap,grid13VO,tasks.getId());
                //获取建筑类型在不同破坏程度下的概率值
                Map<String,BigDecimal> resultMap = new HashMap<>();
                calculationByFortification(grid13VO,listMapMap,psValue,"2",grid13VO.getTotalArea(),resultMap);
                //calculationList = getListCalculation(resultMap,grid13VO);
                //汇总相同格网的不同建筑结构的数据
                List<ResistEarthquakesPECalculation> conditionValue = getConditionValue(resultMap, tasks,grid13VO.getTotalArea(),grid13VO);
                finaConditionValue.addAll(conditionValue);
            }
            //入库
            if (finaConditionValue.size() > 0) {
                resistEarthquakesPERepository.batchCalculation(finaConditionValue);
            }
        }
    }

    //将房屋单体转换成Grid13VO
    private Grid13VO get13VO(BuildingIndividualEntity obj,Map<String, String> dictItemLevel1,Map<String, String> dictItemLevel2) {
        Grid13VO grid13VO = new Grid13VO();
        //写入面积
        grid13VO.setTotalArea(Double.valueOf(obj.getArea()));
        //写入设防占比
        grid13VO.setSfIntensity(0.00);
        grid13VO.setSfIntensity6(0.00);
        grid13VO.setSfIntensity7(0.00);
        grid13VO.setSfIntensity8(0.00);
        grid13VO.setSfIntensity9(0.00);
        if ("0".equals(obj.getIntensity())) {
            grid13VO.setSfIntensity(100.00);
        } else if ("6".equals(obj.getIntensity())) {
            grid13VO.setSfIntensity6(100.00);
        } else if ("7".equals(obj.getIntensity())) {
            grid13VO.setSfIntensity7(100.00);
        } else if ("8".equals(obj.getIntensity())) {
            grid13VO.setSfIntensity8(100.00);
        } else if ("9".equals(obj.getIntensity())) {
            grid13VO.setSfIntensity9(100.00);
        }
        grid13VO.setProvince(obj.getProvince());
        grid13VO.setCity(obj.getCity());
        grid13VO.setCounty(obj.getCounty());
        grid13VO.setId(obj.getId());

        String level1Name = dictItemLevel1.get(obj.getStructureType1());
        String leve21Name = dictItemLevel2.get(obj.getStructureType2());
        if(StringUtils.isNotBlank(leve21Name)){
            level1Name+=("_"+leve21Name);
        }
        grid13VO.setStructureType(level1Name);
        return grid13VO;
    }
    /**
     * 以行政区域为单位组建易损性数据
     */
    private void buildYsxMap(Map<String, Map<String, List<YSXMainTable>>> listMapMap,Grid13VO obj,String taskId){
        if (!listMapMap.containsKey(obj.getProvince() + "_" + obj.getCity() + "_" + obj.getCounty())) {
            //格式类型 <结构类型-设防烈度,<破坏程度，实体对象>>
            Map<String, List<YSXMainTable>> ysxMap = ysxUtil.ysxEncapsulationNew1(taskId, obj.getProvince(), obj.getCity(), obj.getCounty());
            listMapMap.put(obj.getProvince() + "_" + obj.getCity() + "_" + obj.getCounty(), ysxMap);
        }
    }
    /**
     * 组建中间数据
     */
    private List<Calculation> getListCalculation(Map<String,BigDecimal> resultMap,Grid13VO obj){
        List<Calculation> calculationList = new ArrayList<>();
        resultMap.forEach((k,v)->{
            Calculation calculation = new Calculation();
            //格网id
            calculation.setExtends1(obj.getExtends1());
            //省市县
            calculation.setProvince(obj.getProvince());
            calculation.setCity(obj.getCity());
            calculation.setCounty(obj.getCounty());
            //破坏程度
            calculation.setDamage(k);
            //计算值
            calculation.setValue(v);
            //单个面积
            calculation.setArea(BigDecimal.valueOf(obj.getTotalArea()));
            calculation.setGeom(obj.getGeom());
            calculationList.add(calculation);
        });
        return calculationList;
    }

    /**
     * 火鬃相同格网的不同建筑物结构的数据
     */
    private List<ResistEarthquakesPECalculation> getConditionValue(Map<String,BigDecimal> resultMap, CalculationTasks tasks, double gridTotalArea,Grid13VO grid) {
        List<ResistEarthquakesPECalculation> list = new ArrayList<>();
        //collect.forEach((k,v)->{
            //格网总面积
            BigDecimal area = BigDecimal.valueOf(gridTotalArea);
            //按相同破坏程度进行分组
            resultMap.forEach((k1,v1)->{
                ResistEarthquakesPECalculation obj = new ResistEarthquakesPECalculation();
                //k1是破坏程度  v1是数据结果
                //对相同破坏程度的计算值进行累加计算
                BigDecimal value = v1;
                if(area.compareTo(BigDecimal.ZERO) == 0 && value.compareTo(BigDecimal.ZERO) == 0){
                    value = BigDecimal.valueOf(9999.9999);
                }
                obj.setId(UUIDGenerator.getUUID());
                obj.setAssessId(tasks.getId());
                obj.setAssessCode(tasks.getAssessCode());
                //省市县
                obj.setProvinceName(grid.getProvince());
                obj.setCityName(grid.getCity());
                obj.setCountyName(grid.getCounty());
                //格网id
                obj.setExtends1(grid.getExtends1());
                obj.setGeographyId(grid.getExtends1());
                //破坏状态
                obj.setDamageDegree(k1);
                //计算值
                obj.setPt(value);
                //修正值
                obj.setCorrectionValuePt(value);
                //geom
                obj.setGeom(grid.getGeom());
                //写入面积
                obj.setArea(area);
                obj.setCreateUser(PlatformSessionContext.getUserID());
                obj.setDelFlag(YNEnum.N.toString());
                //年份
                obj.setYears(tasks.getYear());
                obj.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
                list.add(obj);
            });
        //});
        return list;
    }

    /**
     * 获取建筑类型在不同破坏程度下的概率值
     */
    private void calculationByFortification(Grid13VO obj,Map<String, Map<String, List<YSXMainTable>>> listMapMap,List<PsHazardDataValue> psHazardDataValues,String type,double gridTotalArea, Map<String,BigDecimal> resultMap){
        if(gridTotalArea==0.0){
            BigDecimal pgcd2Val = resultMap.get("pgcd2");
            if(PlatformObjectUtils.isEmpty(pgcd2Val)){
                pgcd2Val = BigDecimal.ZERO;
            }
            pgcd2Val = pgcd2Val.add(BigDecimal.ZERO);
            resultMap.put("pgcd2",pgcd2Val);
            BigDecimal pgcd3Val = resultMap.get("pgcd3");
            if(PlatformObjectUtils.isEmpty(pgcd3Val)){
                pgcd3Val = BigDecimal.ZERO;
            }
            pgcd3Val = pgcd3Val.add(BigDecimal.ZERO);
            resultMap.put("pgcd3",pgcd3Val);
            BigDecimal pgcd4Val = resultMap.get("pgcd4");
            if(PlatformObjectUtils.isEmpty(pgcd4Val)){
                pgcd4Val = BigDecimal.ZERO;
            }
            pgcd4Val = pgcd4Val.add(BigDecimal.ZERO);
            resultMap.put("pgcd4",pgcd4Val);
            BigDecimal pgcd5Val = resultMap.get("pgcd5");
            if(PlatformObjectUtils.isEmpty(pgcd5Val)){
                pgcd5Val = BigDecimal.ZERO;
            }
            pgcd5Val = pgcd5Val.add(BigDecimal.ZERO);
            resultMap.put("pgcd5",pgcd5Val);
        }else{
            ArrayList<BigDecimal> list = new ArrayList<>();
            //计算 计算的时候传入易损性数据
            //某结构在轻微破坏情况下的概率值
            BigDecimal plVal = BigDecimal.ZERO;
            //某结构在中等破坏情况下的概率值
            BigDecimal pmVal = BigDecimal.ZERO;
            //某结构在严重破坏情况下的概率值
            BigDecimal psVal = BigDecimal.ZERO;
            //某结构在倒塌情况下的概率值
            BigDecimal pdVal = BigDecimal.ZERO;
            //如果不设防不等于0
            if (obj.getSfIntensity() >= 0.0009) {
                //获取某种建筑结构在未设防下的不同破坏程度额概率值
                Map<String, BigDecimal> map = publicMath(obj, "未设防", listMapMap, psHazardDataValues,type,gridTotalArea);
                plVal = plVal.add(map.get("plVal"));
                pmVal = pmVal.add(map.get("pmVal"));
                psVal = psVal.add(map.get("psVal"));
                pdVal = pdVal.add(map.get("pdVal"));
            }
            //如果现设防烈度_6度房屋面积占比不等于0
            if (obj.getSfIntensity6() >= 0.0009) {
                //获取某种建筑结构在设防烈度为6度下的不同破坏程度额概率值
                Map<String, BigDecimal> map = publicMath(obj, "6度", listMapMap, psHazardDataValues,type,gridTotalArea);
                plVal =  plVal.add(map.get("plVal"));
                pmVal = pmVal.add(map.get("pmVal"));
                psVal = psVal.add(map.get("psVal"));
                pdVal = pdVal.add(map.get("pdVal"));
            }
            //如果现设防烈度_7度房屋面积占比不等于0
            if (obj.getSfIntensity7() >= 0.0009) {
                //获取某种建筑结构在设防烈度为7度下的不同破坏程度额概率值
                Map<String, BigDecimal> map = publicMath(obj, "7度", listMapMap, psHazardDataValues,type,gridTotalArea);
                plVal = plVal.add(map.get("plVal"));
                pmVal = pmVal.add(map.get("pmVal"));
                psVal = psVal.add(map.get("psVal"));
                pdVal = pdVal.add(map.get("pdVal"));
            }
            //如果现设防烈度_8度房屋面积占比不等于0
            if (obj.getSfIntensity8() >= 0.0009) {
                //获取某种建筑结构在设防烈度为8度下的不同破坏程度额概率值
                Map<String, BigDecimal> map = publicMath(obj, "8度", listMapMap, psHazardDataValues,type,gridTotalArea);
                plVal = plVal.add(map.get("plVal"));
                pmVal = pmVal.add(map.get("pmVal"));
                psVal = psVal.add(map.get("psVal"));
                pdVal = pdVal.add(map.get("pdVal"));
            }
            //如果现设防烈度_9度房屋面积占比不等于0
            if (obj.getSfIntensity9() >= 0.0009) {
                //获取某种建筑结构在设防烈度为9度下的不同破坏程度额概率值
                Map<String, BigDecimal> map = publicMath(obj, "9度", listMapMap, psHazardDataValues,type,gridTotalArea);
                plVal = plVal.add(map.get("plVal"));
                pmVal = pmVal.add(map.get("pmVal"));
                psVal = psVal.add(map.get("psVal"));
                pdVal = pdVal.add(map.get("pdVal"));
            }
            //如果全部设防烈度都是空或都是0的话则按照未设防计算
            if(PlatformObjectUtils.isEmpty(obj.getSfIntensity()) && PlatformObjectUtils.isEmpty(obj.getSfIntensity6()) && PlatformObjectUtils.isEmpty(obj.getSfIntensity7()) && PlatformObjectUtils.isEmpty(obj.getSfIntensity8()) && PlatformObjectUtils.isEmpty(obj.getSfIntensity9())){
                //获取某种建筑结构在未设防下的不同破坏程度额概率值
                Map<String, BigDecimal> map = publicMath(obj, "未设防", listMapMap, psHazardDataValues,type,gridTotalArea);
                plVal = plVal.add(map.get("plVal"));
                pmVal = pmVal.add(map.get("pmVal"));
                psVal = psVal.add(map.get("psVal"));
                pdVal = pdVal.add(map.get("pdVal"));
            }
            if(obj.getSfIntensity()<0.0009 && obj.getSfIntensity6()<0.0009 && obj.getSfIntensity7()<0.0009 && obj.getSfIntensity8()<0.0009 && obj.getSfIntensity8()<0.0009){
                //获取某种建筑结构在未设防下的不同破坏程度额概率值
                Map<String, BigDecimal> map = publicMath(obj, "未设防", listMapMap, psHazardDataValues,type,gridTotalArea);
                plVal = plVal.add(map.get("plVal"));
                pmVal = pmVal.add(map.get("pmVal"));
                psVal = psVal.add(map.get("psVal"));
                pdVal = pdVal.add(map.get("pdVal"));
            }
            //pgcd2-pgcd4分别代表轻微破坏-倒塌的破坏程度
            BigDecimal pgcd2Val = resultMap.get("pgcd2");
            if(PlatformObjectUtils.isEmpty(pgcd2Val)){
                pgcd2Val = BigDecimal.ZERO;
            }
            pgcd2Val = pgcd2Val.add(plVal);
            resultMap.put("pgcd2",pgcd2Val);
            BigDecimal pgcd3Val = resultMap.get("pgcd3");
            if(PlatformObjectUtils.isEmpty(pgcd3Val)){
                pgcd3Val = BigDecimal.ZERO;
            }
            pgcd3Val = pgcd3Val.add(pmVal);
            resultMap.put("pgcd3",pgcd3Val);
            BigDecimal pgcd4Val = resultMap.get("pgcd4");
            if(PlatformObjectUtils.isEmpty(pgcd4Val)){
                pgcd4Val = BigDecimal.ZERO;
            }
            pgcd4Val = pgcd4Val.add(psVal);
            resultMap.put("pgcd4",pgcd4Val);
            BigDecimal pgcd5Val = resultMap.get("pgcd5");
            if(PlatformObjectUtils.isEmpty(pgcd5Val)){
                pgcd5Val = BigDecimal.ZERO;
            }
            pgcd5Val = pgcd5Val.add(pdVal);
            resultMap.put("pgcd5",pgcd5Val);
        }
    }

    /**
     * 获取某种建筑结构在不同设防烈度下的不同破坏程度额概率值
     */
    private Map<String,BigDecimal> publicMath(Grid13VO obj,String sfqk,Map<String, Map<String, List<YSXMainTable>>> listMapMap,List<PsHazardDataValue> psHazardDataValues,String type,double gridTotalArea){
        //结构类型
        Map<String,BigDecimal> map = new HashMap<>();
        String structureTypeName = "";
        if("1".equals(type)){
            structureTypeName = YSXUtil.getStructureType( obj.getDictionary());
        }else{
            structureTypeName = obj.getStructureType();
        }
        if(!structureTypeName.contains("-")){
            structureTypeName = (structureTypeName+"-"+structureTypeName);
        }
        //格式类型 <省_市_区县,<结构类型-设防烈度,List<实体对象>>>
        Map<String, List<YSXMainTable>> listMap = listMapMap.get(obj.getProvince() + "_" + obj.getCity() + "_" + obj.getCounty());
        //<结构类型-烈度,List<实体对象>>
        List<YSXMainTable> sfList = listMap.get(structureTypeName + "_" + sfqk);
        Map<String, BigDecimal> fImValueMap = buildPsHazardDataValueMap(psHazardDataValues);
        Double  sfIntensity = 0.0;
        //获取当前设防状态占比
        if("未设防".equals(sfqk)){
            if(obj.getSfIntensity() == 0.0 && obj.getSfIntensity6() == 0.0 && obj.getSfIntensity7() == 0.0 && obj.getSfIntensity8() == 0.0 && obj.getSfIntensity9() == 0.0){
                sfIntensity = 100.00;
            }else{
                sfIntensity = obj.getSfIntensity();
            }
        }else if("6度".equals(sfqk)){
            sfIntensity = obj.getSfIntensity6();
        }else if("7度".equals(sfqk)){
            sfIntensity = obj.getSfIntensity7();
        }else if("8度".equals(sfqk)){
            sfIntensity = obj.getSfIntensity8();
        }else if("9度".equals(sfqk)){
            sfIntensity = obj.getSfIntensity9();
        }
        BigDecimal bigDecimal = BigDecimal.valueOf(sfIntensity).divide(BigDecimal.valueOf(100),8, BigDecimal.ROUND_DOWN);
        //设防烈度面积s
        BigDecimal multiply = BigDecimal.valueOf(obj.getTotalArea()).multiply(bigDecimal);
        BigDecimal plVal = BigDecimal.ZERO;
        //某结构在中等破坏情况下的概率值
        BigDecimal pmVal = BigDecimal.ZERO;
        //某结构在严重破坏情况下的概率值
        BigDecimal psVal = BigDecimal.ZERO;
        //某结构在倒塌情况下的概率值
        BigDecimal pdVal = BigDecimal.ZERO;
        //按照地震烈度分组
        Map<String, List<YSXMainTable>> instensityMap = sfList.stream().collect(Collectors.groupingBy(YSXMainTable::getIntensity));
        BigDecimal ctL = new BigDecimal(0);
        BigDecimal ctM = BigDecimal.ZERO;
        BigDecimal ctS = BigDecimal.ZERO;
        BigDecimal ctD = BigDecimal.ZERO;
        /**
         * 破坏程度	   VI        VII    VIII    IX      X
         * 基本完好	   54.93 	25.35 	5.00 	0.55 	0.07
         * 轻微破坏	   26.55 	31.93 	11.23 	1.29 	0.67
         * 中等破坏	   15.52 	35.64 	56.13 	36.05 	8.51
         * 严重破坏	   2.00 	6.08 	26.15 	57.94 	77.66
         * 倒塌	       1.00 	1.00 	1.49 	4.17 	13.09
         */
        /**
         * 发生概率		0.04g	  0.09g	    0.19g	  0.38g	    0.75g
         * 		     	0.00971	  0.00415	0.00106	  0.00012	0.00001
         */
        //砖混结构类型、VI度下P(VI)=0.00971*（26.55%+15.52%+2.00%+1.00%）
        /**
         * 下面求的是转换结构在轻微破坏条件下的概率值
         * VII度P(VII)=0.00415*（31.93%+15.52%+6.08%+1.00%）
         * VIII度P(VIII)=0.00106*（11.23%+56.13%+26.15%+1.49%）
         * IX度P(IX)=0.00012*（1.29%+36.05%+57.94%+4.17%）
         * X度P(IX)=0.00001*（0.67%+8.51%+77.66%+13.09%）
         * P(砖混)=S(砖混)*（P(VI)+P(VII)。。。+P(XII)））/S
         * S(砖混)是砖混结果在未设防下的面积  s是obj的总面积 P(砖混)是砖混在未设防的下概率值
         * 最终的P（砖混轻微破坏） = P(砖混未设防)+ P(砖混设防烈度为6)+ P(砖混设防烈度为7)+ P(砖混设防烈度为8)++ P(砖混设防烈度为9)
         * 格网轻微破坏的概率值= P（砖混轻微破坏） + P（钢混轻微破坏）+.....
         * 中等的、严重的和倒塌的和轻微破坏的计算方法相同
         */
        Iterator<Map.Entry<String, List<YSXMainTable>>> iterator = instensityMap.entrySet().iterator();
        Map.Entry<String, List<YSXMainTable>> next ;
        while(iterator.hasNext()){
            next = iterator.next();
            String k = next.getKey();
            if("5度".equals(k)){
                continue;
            }
            List<YSXMainTable> v = next.getValue();
            //k是地震烈度（6度-10度）  v是该烈度下的数据
            //未设防轻微破坏的
            BigDecimal centerResultL = BigDecimal.ZERO;
            //未设防中等破坏的
            BigDecimal centerResultM = BigDecimal.ZERO;
            //未设防严重破坏的
            BigDecimal centerResultS = BigDecimal.ZERO;
            //未设防倒塌
            BigDecimal centerResultD = BigDecimal.ZERO;

            //基本完好不参与计算
            Map<String, String> damageRatioMap = v.stream().filter(ysxMainTable -> !"基本完好".equals(ysxMainTable.getDamage())).collect(Collectors.toMap(YSXMainTable::getDamage, YSXMainTable::getRate));
            BigDecimal ratioL = BigDecimal.ZERO;
            if(PlatformObjectUtils.isNotEmpty(damageRatioMap.get("轻微破坏"))){
                ratioL = removePercentAndDivide100(damageRatioMap.get("轻微破坏"));
                centerResultL = centerResultL.add(ratioL);
            }
            BigDecimal ratioM = BigDecimal.ZERO;
            if(PlatformObjectUtils.isNotEmpty(damageRatioMap.get("中等破坏"))){
                ratioM = removePercentAndDivide100(damageRatioMap.get("中等破坏"));
                centerResultL = centerResultL.add(ratioM);
                centerResultM = centerResultM.add(ratioM);
            }
            BigDecimal ratioS = BigDecimal.ZERO;
            if(PlatformObjectUtils.isNotEmpty(damageRatioMap.get("严重破坏"))){
                ratioS = removePercentAndDivide100(damageRatioMap.get("严重破坏"));
                centerResultL = centerResultL.add(ratioS);
                centerResultM = centerResultM.add(ratioS);
                centerResultS = centerResultS.add(ratioS);
            }
            BigDecimal ratioD = BigDecimal.ZERO;
            if(PlatformObjectUtils.isNotEmpty(damageRatioMap.get("倒塌"))){
                ratioD = removePercentAndDivide100(damageRatioMap.get("倒塌"));
                centerResultL = centerResultL.add(ratioD);
                centerResultM = centerResultM.add(ratioD);
                centerResultS = centerResultS.add(ratioD);
                centerResultD = centerResultD.add(ratioD);
            }
            //轻微破坏
            BigDecimal fImValueL = fImValueMap.get(k);
            try {
                centerResultL = fImValueL.multiply(centerResultL);
                ctL = ctL.add(centerResultL);
            }catch (Exception e){
                e.printStackTrace();
            }
            //中等破坏
            BigDecimal fImValueM = fImValueMap.get(k);
            centerResultM = fImValueM.multiply(centerResultM);
            ctM = ctM.add(centerResultM);
            //严重破坏
            BigDecimal fImValueS = fImValueMap.get(k);
            centerResultS = fImValueS.multiply(centerResultS);
            ctS = ctS.add(centerResultS);
            //倒塌
            BigDecimal fImValueD = fImValueMap.get(k);
            centerResultD = fImValueD.multiply(centerResultD);
            ctD = ctD.add(centerResultD);
        }

        //某中结构在某种设防度下的轻微破坏程度下的概率值
        plVal = multiply.multiply(ctL).divide(BigDecimal.valueOf(gridTotalArea),8, BigDecimal.ROUND_DOWN);
        map.put("plVal",plVal);
        //某中结构在某种设防度下的中等破坏程度下的概率值
        pmVal = multiply.multiply(ctM).divide(BigDecimal.valueOf(gridTotalArea),8, BigDecimal.ROUND_DOWN);
        map.put("pmVal",pmVal);
        //某中结构在某种设防度下的严重破坏程度下的概率值
        psVal = multiply.multiply(ctS).divide(BigDecimal.valueOf(gridTotalArea),8, BigDecimal.ROUND_DOWN);
        map.put("psVal",psVal);
        //某中结构在某种设防度下的倒塌程度下的概率值
        pdVal = multiply.multiply(ctD).divide(BigDecimal.valueOf(gridTotalArea),8, BigDecimal.ROUND_DOWN);
        map.put("pdVal",pdVal);
        return map;
    }

    private BigDecimal removePercentAndDivide100(String ratio){
        String temp = ratio.replace("%", "");
        return new BigDecimal(temp).divide(BigDecimal.valueOf(100),8, BigDecimal.ROUND_DOWN);
    }

    /**
     * 构建形如<6度，5>这样的数据
     */
    private Map<String,BigDecimal> buildPsHazardDataValueMap(List<PsHazardDataValue> psHazardDataValues){
        Map<String,BigDecimal> psHazardDataValueMap = new HashMap<>();
        for (PsHazardDataValue psHazardDataValue : psHazardDataValues) {
            String imValue = psHazardDataValue.getImValue();
            String realIntensity = getRealIntensity(imValue);
            psHazardDataValueMap.put(realIntensity,psHazardDataValue.getFImValue());
        }
        return psHazardDataValueMap;
    }

    /**
     * 获取例如6度这样格式的烈度数据
     */
    private String getRealIntensity( String imValue){
        if (null == imValue) {
            return null;
        }
        switch (imValue) {
            case "0.04g":
                return "6度";
            case "0.09g":
                return "7度";
            case "0.19g":
                return "8度";
            case "0.38g":
                return "9度";
            case "0.75g":
                return "10度";
            default:
                return null;
        }
    }

    /**
     * 获取相同格网的数据
     */
    private Map<String, List<PsHazardDataValue>> getIdGroupData(String unionGeomByCode,CalculationTasks tasks){
        Map<String, List<PsHazardDataValue>> mapVXX = null;
        List<PsHazardDataValue> psHazardDataValueList = publicOperateService.getPsHazardDataValueList1(tasks.getLdPga(), unionGeomByCode,tasks);
        if(PlatformObjectUtils.isNotEmpty(psHazardDataValueList) && psHazardDataValueList.size()>0){
            //分组构建相同的格网id数据的为一组
            mapVXX = psHazardDataValueList.stream().filter(psHazardDataValue -> StringUtils.isNotBlank(psHazardDataValue.getId()))
                    .collect(Collectors.groupingBy(PsHazardDataValue::getId));
        }
        return mapVXX;
    }

    private String getUnionGeomByCode(CalculationTasks tasks) throws Exception {
        //根据所有省市县获取省市县geom
        String unionGeomByCode = "";
        if ("0".equals(tasks.getRadio2())) {
            //0为省市区县
            //根据所有省市县获取省市县geom
            unionGeomByCode = publicOperateService.getUnionGeomByCode(tasks.getList());
            //得到该区域内所有的省市县。
        } else if ("1".equals(tasks.getRadio2())) {
            //1为地图圈选
            //写入地图圈选geom
            unionGeomByCode = tasks.getCoordinateRange();
        }
        return unionGeomByCode;
    }
}
